import console from './console';
import * as crypto from 'crypto';
import moment from 'moment-es6';
import * as Redis from 'ioredis';
import * as jwt from 'jwt-simple';
import * as uuid from 'uuid';
import { appConfig } from '../app.config';

class Business {
    // private static instance: Business;
    private redisClient: Redis.Redis;

    constructor() {
        this.redisClient = new Redis(appConfig.redisConfig);
    }

    getRedisClient() {
        return this.redisClient;
    }

    jwtDecrypt(valueToDecrypt: string, signKey?: string) {
        let decodeString = null;
        this.executeStatement(() => {
            decodeString = jwt.decode(valueToDecrypt, signKey || appConfig.encryptKey, true, 'HS256');
        });
        return decodeString;
    }

    jwtEncrypt(valueToEncrypt: any, signKey?: string) {
        return jwt.encode(valueToEncrypt, signKey || appConfig.encryptKey, 'HS256');
    }

    // static getInstance() {
    //     if (!Business.instance) {
    //         Business.instance = new Business();
    //     }
    //     return Business.instance;
    // }

    async executeStatement(tryFunction: () => void, catchFunction?: (e?: Error) => void, finallyFunction?: () => void) {
        try {
            tryFunction && (await tryFunction());
        } catch (e) {
            console.error(e);
            catchFunction && (await catchFunction(e));
        } finally {
            finallyFunction && (await finallyFunction());
        }
    }

    sleep(timeout: number = 500) {
        return new Promise(resolve => {
            setTimeout(resolve, timeout);
        });
    }

    getNewId() {
        return uuid.v4().replace(/-/g, '');
    }

    getNow() {
        return moment().unix();
    }

    getNowAfterHour(hour: number) {
        return moment().add(hour, 'h').unix();
    }

    getNowAfterDay(day: number) {
        return moment().add(day, 'd').unix();
    }

    getNowString() {
        return moment().format('YYYY-MM-DD HH:mm:ss');
    }

    md5(str: string) {
        return crypto.createHash('md5').update(str, 'utf8').digest('hex');
    }

    sha256(str: string, key: string) {
        return crypto.createHmac('sha256', key).update(str, 'utf8');
    }

    toQueryString(obj: object) {
        return Object.keys(obj)
            .filter(key => key !== 'sign' && obj[key] !== undefined && obj[key] !== '')
            .sort()
            .map(key => key + '=' + obj[key])
            .join('&');
    }

    makeSign(params: object, apiSecret: string) {
        let str = 'api_secret=' + apiSecret + '&' + this.toQueryString(params) + '&' + 'api_secret=' + apiSecret;
        return this.md5(str).toUpperCase();
    }

    generateRandom(length = 16) {
        const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let noceStr = '', maxPos = chars.length;
        while (length--) noceStr += chars[(Math.random() * maxPos) | 0];
        return noceStr;
    }
}

export default new Business()
